﻿    global Workbook
    global excel
    global ActiveSheet
    global ActiveCell
    global Selection
    global lLastRow ;整个表的最末尾行
    global lLastColumn ;整个表最末尾列
    global SelectionFirstRow ;当前选择内容首行
    global SelectionFirstColumn ;当前选择内容首列
    global SelectionLastColumn ;当前选择内容末列
    global SelectionLastRow ;当前选择内容末行
    global SelectionType ; 当前选择单元格类型 1=A1  2=A1:B1 4=A1:A2 16=A1:B2  18=A1:B1 A1:B2 20=A1:A2 A1:B2
    global FontColor := -4165632  ;填充字体颜色-默认蓝色
    global CellColor := -16711681 ;填充表格颜色-默认黄色
    global LastSelectSheetIndex:=  ;最后选中的工作表的序号
    ;XlDirection常量
    global xlDown := -4121    ;向下
    global xlToLeft := -4159  ;向左
    global xlToRight := -4161 ;向右
    global xlUp := -4162      ;向上
    ;XlAutoFillType常量
    global xlFillCopy:=1     ;将源区域的值和格式复制到目标区域
    global xlFillDefault:=0     ;确定用于填充目标区域的值和格式
    global xlFillFormats:=3     ;只复制格式
    global xlFillSeries:=2     ;扩展到目标区域，如1,2，扩展到3,4,5
    global xlFillValuse:=4     ;值
    global xlGrowthTrend:=10     ;乘法关系，如1,2，扩展到4,8,16
    global xlLinearTrend:=9     ;加法关系，如1,3，扩展到5,6,9
    ; XlLinestyle常量
    global xlDot:=-4118              ;
    global xlContinuous:=1              ;
    global xlDash:=-4115              ;
    global xlDouble:= -4119             ;
    ; XlBorderWeight常量
    global xlHairline:=1
    global xlMedium:=-4138
    global xlThick:=4
    global xlThin:=2
    ;XlBordersIndex    常量
    global xlDiagonalDown:=5
    global xlDiagonalUp:=6
    global xlEdgeBottom:=9
    global xlEdgeLeft:=7
    global xlEdgeRight:=10
    global xlEdgeTop:=8
    global xlInsideHorizontal:=12
    global xlInsideVertical:=11
    ;XlHAlign   常量
    global xlHAlignCenter	:=-4108
    global xlHAlignCenterAcrossSelection:=	7
    global xlHAlignDistributed	:=-4117
    global xlHAlignFill:=	5
    global xlHAlignGeneral:=	1
    global xlHAlignJustify:=	-4130
    global xlHAlignLeft:=	-4131
    global xlHAlignRight	:=-4152
    ;XlVAlign  常量
    Global xlVAlignBottom:=-4107
    Global xlVAlignCenter:=-4108
    Global xlVAlignDistributed:=-4117
    Global xlVAlignJustify:=-4130
    Global xlVAlignTop:=-4160
    ; XlUnderlineStyle  常量
    Global xlUnderlineStyleDouble:=-4119
    Global xlUnderlineStyleDoubleAccounting:=5
    Global xlUnderlineStyleNone:=-4142
    Global xlUnderlineStyleSingle:=2
    Global xlUnderlineStyleSingleAccounting:=4
    ; XlBuiltInDialog  常量
    Global xlDialogPageSetup:=7
    Global xlDialogSummaryInfo:=474
    Global xlDialogFilter:=447
    Global xlDialogSort:=39
    Global xlDialogDataDelete:=36
    ; XlAutoFilterOperator  常量
    Global xlAnd:=1
    Global xlBottom10Items:=4
    Global xlBottom10Percent:=6
    Global xlFilterCellColor:=8
    Global xlFilterDynamic:=11
    Global xlFilterFontColor:=9
    Global xlFiterIcon:=10
    Global xlFilterValues:=7
    Global xlOr:=2
    Global xlTop10Items:=3
    Global xlTop10Percent:=5
    ; XlWindowView  常量
    Global xlNormalView:=1
    Global xlPageBreakPreview:=2
    ;自定义颜色 常量
    global CBlack:=1    ;黑
    global CWhite:=2    ;白
    global CRed:=3      ;红
    global CGreen:=4    ;绿
    global CBlue:=5     ;蓝
    global CYellow:=6       ;黄
    global CMagenta:=7       ;粉红
    global CCyan:=8       ;青
    global CGray25:=15       ;灰色25
    global CGray40:=48       ;灰色40
    global CGray50:=16       ;灰色50
    global CPurple:=17       ;紫
    global CLightRed:=22      ;浅红
    global CSkyBlue:=33       ;天蓝
    global CCyanGreen:=34       ;浅青绿
    global CLightGreen:=35       ;浅绿
    global CLightYellow:=36       ;浅黄
    global CLightBlue:=37       ;浅蓝
    global CRoseRed:=38       ;玫瑰红
    global CLigthPurple:=39       ;浅紫
    global COrangeBrown:=40       ;茶色
    global CMiddleBlue:=41       ;浅蓝
    global CWaterGreen:=42       ;水绿色
    global CGrassGreen:=43       ;青草绿
    global CGold:=44       ;金
    global CLightOrange:=45       ;浅橙
    global COrange:=46       ;橙
    global CBlueGray:=47       ;蓝灰
    global CDarkCyan:=49       ;深青
    global CMiddleGreen:=50       ;中绿
    global CTan:=53       ;褐
    global CDarkBlue:=55       ;黑蓝
    global CAuto:=-4105       ;自动
    global CNone:=-4142       ;无色

    ;~ excel:=Excel_Get()
    ;~ ActiveSheet:=excel.ActiveSheet
    ;~ ActiveCell:=excel.ActiveCell
    ;~ Selection:=excel.Selection
    ;~ excel.Selection.Interior.ColorIndex:= CYellow
        ;~ ;Selection:= excel.Selection.address(0,0)
        ;~ ;excel.Selection.Interior.ColorIndex := 44
        ;~ excel.Selection.Font.Color := FontColor
        ;~ excel.Selection.Interior.Color := CellColor

;以下代码段为查找选中区域边界
    ;~ excel:=Excel_Get()
    ;~ Selection:=excel.Selection
    ;~ Rngs_left := Selection.Column
    ;~ Rngs_top := Selection.Row
    ;~ Rngs_right := Rngs_left + Selection.Columns.Count - 1
    ;~ Rngs_bottom := Rngs_top + Selection.Rows.Count - 1
    ;~ leftC := StrSplit(excel.Cells(Rngs_top, Rngs_left).Address, "$")[2]
    ;~ rightC := StrSplit(excel.Cells(Rngs_top, Rngs_right).Address, "$")[2]
    ;~ topR:=StrSplit(excel.Cells(Rngs_top, Rngs_left).Address, "$")[3]
    ;~ bottomR:=StrSplit(excel.Cells(Rngs_bottom, Rngs_left).Address, "$")[3]
    ;~ Selected_top_left := leftC . Rngs_top
    ;~ Selected_bottom_right := rightC .  Rngs_bottom
    ;~ Selected_rows_string:=topR . ":" . bottomR
    ;~ Selected_columns_string:=leftC . ":" . rightC
    ;~ Selected_range_string := Selected_top_left .  ":" . Selected_bottom_right
    ;~ Selected_range :=  excel.ActiveSheet.Range(Selected_range_string)
    ;~ Selected_range.Copy

;===================================================================
;直接获取Excel
getExcel()
{
    ;objRelease(excel)
    if (excel.version <> "")
    {
        excel := ComObjCreate("Excel.Application") ; 创建Excel对象
    }
    return excel
}

Excel_ActiveSheet()
{
    ;objRelease(excel)
    Sheet := getExcel().ActiveSheet ; 当前工作表
    return
}

Excel_ActiveCell()
{
    ;objRelease(excel)
    ;excel := ComObjCreate("Excel.Application") ; 创建Excel对象
    Cell := getExcel().ActiveCell ; 当前单元格
    return
}

Excel_Selection()
{
    ;objRelease(excel)
    ;excel := ComObjCreate("Excel.Application") ; 创建Excel对象
    Selection:=getExcel().Selection ;选择对象
    return
}

Excel_Direction(x=0, y=0)
{
    objExcel := Excel_GetObj()
    app  := ObjExcel.Application
    cell := app.ActiveCell
    addr := Cell_Address(cell)
    x_new := CharCalc(Addr["x"],x)
    y_new := addr["y"] + y
    If y_new < 1
        y_new := 1
    new := "$" x_new "$" y_new
    app.range(new).Activate
}

Excel_CellActivate(Location){
    objExcel := Excel_GetObj()
    app  := ObjExcel.Application
    app.range(Location).Activate
}

CharCalc(char,count)
{
    StringUpper,Char,Char
    SingleChars := []
    NumberChars := []
    ReturnChars := []
    MaxBit := Strlen(char)
    SingleChars[0] := MaxBit
    Loop,Parse,Char
    {
        Pos := MaxBit - A_Index + 1
        SingleChars[Pos] := Asc(A_LoopField)-64
    }
    ; 800 => abcd
    idx := 26
    Loop
    {
        If count >= %idx%
            idx := idx * idx
        Else {
            MaxBit := A_Index
            Break
        }
    }
    NumberChars[0] := MaxBit
    Loop % MaxBit
    {
        Pos := MaxBit - A_index
        NumberChars[Pos+1] := Floor(Count/26**Pos)
        count := Mod(count,26**Pos)
    }
    s := SingleChars[0]
    n := NumberChars[0]
    If s > %n%
        MaxBit := s
    Else
        MaxBit := n
    Pos := 1
    Add := 0
    Loop,% MaxBit
    {
        s := SingleChars[Pos]
        If not strlen(s)
            s := 0
        n := NumberChars[Pos]
        If not strlen(n)
            n := 0
        r := ReturnChars[Pos]
        If not strlen(r)
            r := 0
        sum := s + n + r
        If sum > 26
        {
            sum := sum - 26
            ReturnChars[Pos+1] := 1
        }
        ReturnChars[Pos] := sum
        Pos++
    }
    msg := ""
    For  i , k in ReturnChars
        msg := Chr(k+64) msg
    return msg
}

Cell_Address(cell)
{
    addr := []
    OldAddr := Cell.Address()
    Loop,Parse,OldAddr,$
    {
        If not Strlen(A_LoopField)
            Continue
        If Strlen(addr["x"])
            addr["y"] := A_LoopField
        Else
            addr["x"] := A_LoopField
    }
    return addr
}

Excel_GetObj()
{
    ControlGet, hwnd, hwnd, , Excel71, ahk_class MicrosoftExcel
    ObjExcel := Excel[hwnd]
    If IsObject(ObjExcel)
        return ObjExcel
    ObjExcel := Acc_ObjectFromWindow(hwnd, -16)
    Excel[hwnd] := ObjExcel

    return ObjExcel
}

MicrosoftExcel_获取Range地址(address)
{
    StringReplace, address, address, $,,All
    return
}

XLMIAN_获取活动工作表边界()
{
    lLastRow := excel.Cells(excel.Rows.Count, 1).End(-4162).Row
    lLastColumnAddress := excel.Cells(1, excel.Columns.Count).End(-4159).Address
    StringReplace, lLastColumnAddress, lLastColumnAddress, $,,All
    RegExMatch(lLastColumnAddress,"[A-Z]+",lLastColumn)
    return
}

MicrosoftExcel_ColToChar(index)
{
    If(index <= 26)
    {
        return Chr(64+index)
    }
    Else If (index > 26)
    {
        return Chr((index-1)/26+64) . Chr(mod((index - 1),26)+65)
    }
}

XLMIAN_获取Range边界(address)
{
    StringReplace, address, address, $,,All
    FoundPosSeperate := RegExMatch(address,":")
    StringLeft, parta, address, FoundPosSeperate-1
    StringMid, partb, address, FoundPosSeperate+1 , 50
    RegExMatch(parta,"[A-Z]+",ColumnLeftName)
    RegExMatch(parta,"[0-9]+",RowUp)
    ;msgbox,ColumnLeftName%ColumnLeftName% RowUp %RowUp%

    RegExMatch(partb,"[A-Z]+",ColumnRightName)
    RegExMatch(partb,"[0-9]+",RowDown)
    return
}

MicrosoftExcel_GetSelectionType()
{
    if excel.Selection.Columns.Count =1 And excel.Selection.Rows.Count =1 ;A1
    {
        SelectionType:=1
    }
    else if excel.Selection.Columns.Count >1 And excel.Selection.Rows.Count =1 ;A1:B1
    {
        SelectionType:=2
    }
    else if excel.Selection.Columns.Count =1 And excel.Selection.Rows.Count >1 ;A1:A2
    {
        SelectionType:=4
    }
    else if excel.Selection.Columns.Count >1 And excel.Selection.Rows.Count >1  ;A1:B2
    {
        SelectionType:=16
    }
    else
        return
}

MicrosoftExcel_GetSelectionInfo()
{
    address:=excel.Selection.Address
    ;msgbox,address %address%
    StringReplace, address, address, $,,All
    ;msgbox,address %address%

    if SelectionType = 1 ;A1
    {
        ;msgbox,SelectionType %SelectionType%
        RegExMatch(address,"[A-Z]+",SelectionFirstColumn)
        RegExMatch(address,"[0-9]+",SelectionFirstRow)
        ;msgbox,SelectionFirstColumn %SelectionFirstColumn%  SelectionFirstRow %SelectionFirstRow%
        SelectionLastColumn:=SelectionFirstColumn
        SelectionLastRow:=SelectionFirstRow

        return
    }
    else if SelectionType = 2 ;A1:B1
    {
        FoundPosSeperate := RegExMatch(address,":")
        StringLeft, parta, address, FoundPosSeperate-1
        StringMid, partb, address, FoundPosSeperate+1 , 50

        RegExMatch(parta,"[A-Z]+",SelectionFirstColumn)
        RegExMatch(parta,"[0-9]+",SelectionFirstRow)


        RegExMatch(partb,"[A-Z]+",SelectionLastColumn)
        SelectionLastRow:=SelectionFirstRow


    }
    else if SelectionType = 4 ;A1:A2
    {
        FoundPosSeperate := RegExMatch(address,":")
        StringLeft, parta, address, FoundPosSeperate-1
        StringMid, partb, address, FoundPosSeperate+1 , 50

        RegExMatch(parta,"[A-Z]+",SelectionFirstColumn)
        RegExMatch(parta,"[0-9]+",SelectionFirstRow)

        SelectionLastColumn:=SelectionFirstColumn
        RegExMatch(partb,"[0-9]+",SelectionLastRow)
    }
    else if SelectionType = 16  ;A1:B2
    {
        FoundPosSeperate := RegExMatch(address,":")
        StringLeft, parta, address, FoundPosSeperate-1
        StringMid, partb, address, FoundPosSeperate+1 , 50
        RegExMatch(parta,"[A-Z]+",SelectionFirstColumn)
        RegExMatch(parta,"[0-9]+",SelectionFirstRow)
        ;msgbox,ColumnLeftName%ColumnLeftName% RowUp %RowUp%

        RegExMatch(partb,"[A-Z]+",SelectionLastColumn)
        RegExMatch(partb,"[0-9]+",SelectionLastRow)
    }
    else
        return
}

XLFind:
    XLFind()
return

XLFind()
{
    ControlGetText, findstring, Edit1, A
    If not Strlen(findstring)
        return
    If RegExMatch(findstring,"^[a-zA-Z]*$")
        Excel_CellActivate(findstring "1")
    Else
        Excel_CellActivate(findstring)
}


Excel_Get(WinTitle="ahk_class XLMAIN") {	; by Sean and Jethrow, minor modification by Learning one
	ControlGet, hwnd, hwnd, , Excel71, %WinTitle%
	if !hwnd
		return
	Window := Acc_ObjectFromWindow(hwnd, -16)
	Loop
		try
			Application := Window.Application
		catch
			ControlSend, Excel71, {esc}, %WinTitle%
	Until !!Application
	return Application
}	; http://www.autohotkey.com/forum/viewtopic.php?p=492448#492448
return


;------------------------------------------------------------------------------
; Acc.ahk Standard Library
; by Sean
; Updated by jethrow:
; 	Modified ComObjEnwrap params from (9,pacc) --> (9,pacc,1)
; 	Changed ComObjUnwrap to ComObjValue in order to avoid AddRef (thanks fincs)
; 	Added Acc_GetRoleText & Acc_GetStateText
; 	Added additional functions - commented below
; 	Removed original Acc_Children function
;	Added Acc_Error, Acc_ChildrenByRole, & Acc_Get functions
; last updated 10/25/2012
;------------------------------------------------------------------------------

Acc_Init()
{
	Static	h
	If Not	h
		h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "")
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
	Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
}

Acc_ObjectFromWindow(hWnd, idObject = 0)
{
	Acc_Init()
	If	DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
	Return	ComObjEnwrap(9,pacc,1)
}

Acc_WindowFromObject(pacc)
{
	If	DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
	Return	hWnd
}

Acc_GetRoleText(nRole)
{
	nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
	Return	sRole
}

Acc_GetStateText(nState)
{
	nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
	VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
	DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
	Return	sState
}

Acc_SetWinEventHook(eventMin, eventMax, pCallback)
{
	Return	DllCall("SetWinEventHook", "Uint", eventMin, "Uint", eventMax, "Uint", 0, "Ptr", pCallback, "Uint", 0, "Uint", 0, "Uint", 0)
}

Acc_UnhookWinEvent(hHook)
{
	Return	DllCall("UnhookWinEvent", "Ptr", hHook)
}
/*	Win Events:

	pCallback := RegisterCallback("WinEventProc")
	WinEventProc(hHook, event, hWnd, idObject, idChild, eventThread, eventTime)
	{
		Critical
		Acc := Acc_ObjectFromEvent(_idChild_, hWnd, idObject, idChild)
		; Code Here:

	}
*/

; Written by jethrow
Acc_Role(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
}
Acc_State(Acc, ChildId=0) {
	try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
}
Acc_Location(Acc, ChildId=0, byref Position="") { ; adapted from Sean's code
	try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
	catch
		return
	Position := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
	return	{x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")}
}
Acc_Parent(Acc) { 
	try parent:=Acc.accParent
	return parent?Acc_Query(parent):
}
Acc_Child(Acc, ChildId=0) {
	try child:=Acc.accChild(ChildId)
	return child?Acc_Query(child):
}
Acc_Query(Acc) { ; thanks Lexikos - www.autohotkey.com/forum/viewtopic.php?t=81731&p=509530#509530
	try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Error(p="") {
	static setting:=0
	return p=""?setting:setting:=p
}
Acc_Children(Acc) {
	if ComObjType(Acc,"Name") != "IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren%
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
			return Children.MaxIndex()?Children:
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_ChildrenByRole(Acc, Role) {
	if ComObjType(Acc,"Name")!="IAccessible"
		ErrorLevel := "Invalid IAccessible Object"
	else {
		Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
		if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
			Loop %cChildren% {
				i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i)
				if NumGet(varChildren,i-8)=9
					AccChild:=Acc_Query(child), ObjRelease(child), Acc_Role(AccChild)=Role?Children.Insert(AccChild):
				else
					Acc_Role(Acc, child)=Role?Children.Insert(child):
			}
			return Children.MaxIndex()?Children:, ErrorLevel:=0
		} else
			ErrorLevel := "AccessibleChildren DllCall Failed"
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}
Acc_Get(Cmd, ChildPath="", ChildID=0, WinTitle="", WinText="", ExcludeTitle="", ExcludeText="") {
	static properties := {Action:"DefaultAction", DoAction:"DoDefaultAction", Keyboard:"KeyboardShortcut"}
	AccObj :=   IsObject(WinTitle)? WinTitle
			:   Acc_ObjectFromWindow( WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0 )
	if ComObjType(AccObj, "Name") != "IAccessible"
		ErrorLevel := "Could not access an IAccessible Object"
	else {
		StringReplace, ChildPath, ChildPath, _, %A_Space%, All
		AccError:=Acc_Error(), Acc_Error(true)
		Loop Parse, ChildPath, ., %A_Space%
			try {
				if A_LoopField is digit
					Children:=Acc_Children(AccObj), m2:=A_LoopField ; mimic "m2" output in else-statement
				else
					RegExMatch(A_LoopField, "(\D*)(\d*)", m), Children:=Acc_ChildrenByRole(AccObj, m1), m2:=(m2?m2:1)
				if Not Children.HasKey(m2)
					throw
				AccObj := Children[m2]
			} catch {
				ErrorLevel:="Cannot access ChildPath Item #" A_Index " -> " A_LoopField, Acc_Error(AccError)
				if Acc_Error()
					throw Exception("Cannot access ChildPath Item", -1, "Item #" A_Index " -> " A_LoopField)
				return
			}
		Acc_Error(AccError)
		StringReplace, Cmd, Cmd, %A_Space%, , All
		properties.HasKey(Cmd)? Cmd:=properties[Cmd]:
		try {
			if (Cmd = "Location")
				AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
			  , ret_val := "x" NumGet(x,0,"int") " y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")
			else if (Cmd = "Object")
				ret_val := AccObj
			else if Cmd in Role,State
				ret_val := Acc_%Cmd%(AccObj, ChildID+0)
			else if Cmd in ChildCount,Selection,Focus
				ret_val := AccObj["acc" Cmd]
			else
				ret_val := AccObj["acc" Cmd](ChildID+0)
		} catch {
			ErrorLevel := """" Cmd """ Cmd Not Implemented"
			if Acc_Error()
				throw Exception("Cmd Not Implemented", -1, Cmd)
			return
		}
		return ret_val, ErrorLevel:=0
	}
	if Acc_Error()
		throw Exception(ErrorLevel,-1)
}

CustomAutoFilter(ArithmeticOpr, CurrentValue,period_buff)
{
    try
    {
        fid:=
        fid_first_column:=
        CriteriaValue:=
        FilteredRowColon:=
        FilteredRow:=
        FilteredColumn:=
        c:=
        r:=
        b:=
        rgb:=
        ;~ if RegExMatch(CurrentValue,"\.")
        ;~ {
            ;~ CurrentValue:=RegExReplace(CurrentValue,"0*$","")      ;进行数值换算，去除多余的小数0
            ;~ CurrentValue:=RegExReplace(CurrentValue,"\.$","")      ;进行数值换算，去除最后的点
        ;~ }
        CriteriaValue := ArithmeticOpr . CurrentValue    
        ;~ msgbox % CriteriaValue
        
        excel:=Excel_Get()
        ActiveSheet:=excel.ActiveSheet
        ActiveCell:=excel.ActiveCell
        Selection:=excel.Selection
        FilteredColumn := StrSplit(ActiveSheet.AutoFilter.Range.Columns(1).Address, "$")(2)
        FilteredRowColon := StrSplit(ActiveSheet.AutoFilter.Range.Rows(1).Address, "$")(3)
        FilteredRow := StrSplit(FilteredRowColon, ":")(1)

        fid_first_column := excel.ActiveSheet.Range(FilteredColumn "1:"   FilteredColumn   "1").Column
        fid := ActiveCell.Column - fid_first_column + 1

        If (period_buff = "fa"){
            excel.ActiveSheet.Range("A1").CurrentRegion.AutoFilter(Field:=fid)
        } Else If (period_buff = "fc") Or (period_buff = "f'")  {  ;
            excel.ActiveSheet.Range("A1").CurrentRegion.AutoFilter(Field:=fid,,Operator:=xlFilterFontColor)
        ;~ } Else If (period_buff = "f=") {  ;
            ;~ excel.ActiveSheet.Range("A1").CurrentRegion.AutoFilter(Field:=fid,Criteria1:=CriteriaValue)
        } Else If (period_buff = "f;")   {
           
            TemColor:=ActiveCell.Interior.color
            SetFormat, integerFast, hex
            msgbox % TemColor
            c := substr("000000"  TemColor, -5)
            r:=substr(c,1,2)
            g:=substr(c,3,2)
            b:=substr(5,2)
            SetFormat, IntegerFast, d
            r:=r
            g:=g
            b:=b
            rgb := "RGB(" . r . "," . g . "," . b . ")"
            MsgBox rgb
            excel.ActiveSheet.Range("A1").CurrentRegion.AutoFilter(Field:=fid, Criteria1:=rgb, Operator:=xlFilterCellColor)
        } Else {
          excel.ActiveSheet.Range("A1").CurrentRegion.AutoFilter(Field:=fid, Criteria1:=CriteriaValue)
        }
    }
}

ShowFilterDialog()
 {
    global xlDialogFilter
    fid:=
    fid_first_column:=
    CriteriaValue:=
    FilteredRowColon:=
    FilteredRow:=
    FilteredColumn:=
    excel:=Excel_Get()
    ActiveSheet:=excel.ActiveSheet
    ActiveCell:=excel.ActiveCell
    Selection:=excel.Selection
    
    FilteredColumn := strSplit(excel.ActiveSheet.AutoFilter.Range.Columns(1).Address, "$")[2]
    FilteredRowColon := strSplit(excel.ActiveSheet.AutoFilter.Range.Rows(1).Address, "$")[3]
    FilteredRow := strSplit(FilteredRowColon, ":")[1]
    
    fid_first_column := excel.ActiveSheet.Range(FilteredColumn   "1:"   FilteredColumn  "1").Column
    fid := ActiveCell.Column - fid_first_column + 1
    ;~ msgbox % fid
    ;~ excel.Dialogs(xlDialogFilter).Show fid, ActiveCell.Value
    ;~ if (excel.AutoFilterMode)
        ;~ excel.Dialogs(447).Show fid, ActiveCell.Value
    ;~ else
        excel.Dialogs(447).Show
    
}